#pragma once

#include "..\\ExternalTools\\ExternalTools.h"

#include "..\\Loirey\\loirey_GLOBAL.h"
#include "..\\Loirey\\loirey_BasicStructure.h"

#include "..\\Classification.Base\cl_base_Data.h"
#include "..\\Classification.Base\cl_base_BinaryClassification.h"

class CCosineKNN_Model : public CBinaryClassifier
{
public:
	class CParameters
	{
	public:
		static const int TRANSPOSE_MODE_BY_EXAMPLE = 0;
		static const int TRANSPOSE_MODE_BY_FEATURE = 1;
	public:
		int K;
		int TransposeMode;
		string strFN_TrainData;
		
	public:
		CParameters();
	public:
		virtual bool InputFromStream(istream& inStream);
		virtual void OutputToStream(ostream& outStream) const;
	};
public:
	class CInnerExampleRecord
	{
	public:
		int Index;
		int Label;
		double Weight;
		double Similarity;

	public:
		static bool CompareByIndex(const CInnerExampleRecord& a, const CInnerExampleRecord& b);
		static bool CompareByLabel(const CInnerExampleRecord& a, const CInnerExampleRecord& b);
		static bool CompareBySimilarity(const CInnerExampleRecord& a, const CInnerExampleRecord& b);
	};
public:
	typedef CLabelValueMapping<int,double> CMapping_ExampleSimilarity;

public:
	CParameters Parameters;
public:
	int ExampleAmount, FeatureDimension;
	CSimpleTypeArray<int> ExampleLabelList;
	CSimpleTypeArray<double> ExampleWeightList;
public:
	CMyNormalizer_L2_NORM MyNormalizer;
	CDataSetForBinaryClassification BinaryClassificationLabelSettings;
public:
	CSimpleTypeArray<CInnerExampleRecord> InnerExampleRecordList;
	CMapping_ExampleSimilarity MES;
	CSparseVector ClassifyResult;
public:
	C_LDS_Sparse_ByExample TrainData;

public:
	CCosineKNN_Model();
public:
	virtual bool LoadFromFile(string strFN_Model, int ModelMemoryCacheSize_InMB);
	virtual void SaveToFile(string strFN_Model);
protected:
	virtual void _TransposeTrainData(
		CDataSetForClassification* pDataSet_Train, CWeightedClassificationExampleList& ExampleList_Train,
		int TransposeMemoryCacheSize_InMB);
	virtual void _InitTrainData(int ModelMemoryCacheSize_InMB);
public:
	virtual void Train(
		CLabeledDataSetForClassification* pLabelDataSet_Train, CWeightedClassificationExampleList& ExampleList_Train,
		const CParameters& Parameters, int TransposeMemoryCacheSize_InMB, int ModelMemoryCacheSize_InMB);
	virtual void Train(
		CDataSetForClassification* pDataSet_Train, CBinaryClassificationExampleList& BinaryExampleList_Train,
		const CParameters& Parameters, int TransposeMemoryCacheSize_InMB, int ModelMemoryCacheSize_InMB);
public:
	virtual void Classify_ToVector(CDataSetForClassification* pDataSet, int ExampleIndex, CSparseVector& DstResult);
public:
	virtual void Classify_BestLabel(CDataSetForClassification* pDataSet, int ExampleIndex, int& DstPrediction, double& DstConfidence);
protected:
	virtual bool InputFromStream(istream& inStream);
	virtual void OutputToStream(ostream& outStream);
	virtual void _Classify(CDataSetForClassification* pDataSet, int ExampleIndex, double& DstConfidence, int& DstPrediction);
};

